"""
食物热量参照表 Service 层（业务逻辑层）
负责封装食物热量相关业务逻辑，调用 DAO 层进行数据操作
返回格式统一为：(是否成功, 提示信息/数据)
"""
from app.Dao.HealthDao.FoodDao.FoodCalDao import FoodCalDAO  # 假设 DAO 类在 app/dao/food_cal_dao.py
from app.Dao.HealthDao.FoodDao.FoodCateDao import FoodCateDAO  # 用于校验食物类别
from sqlalchemy.exc import IntegrityError, SQLAlchemyError
from app.Services.HealthServices.FoodServices.FoodCateServices import FoodCateServices


class FoodCalServices:
    """食物热量 Service 类，封装业务逻辑"""

    @staticmethod
    def add_food_cal(food_cate_id, food_name, kcal_per_piece, gram_per_piece):
        """
        新增食物热量记录（业务校验：参数非空+类别存在+数值合法）
        :param food_cate_id: 食物类别ID
        :param food_name: 食物名称
        :param kcal_per_piece: 每份热量（kcal）
        :param gram_per_piece: 每份克重（g）
        :return: (bool, str) - (成功标识, 提示信息)
        """
        # 1. 基础参数校验
        if not food_cate_id or not isinstance(food_cate_id, int) or food_cate_id <= 0:
            return False, "食物类别ID必须是正整数"
        if not food_name or food_name.strip() == "":
            return False, "食物名称不能为空"
        if not kcal_per_piece or not isinstance(kcal_per_piece, int) or kcal_per_piece < 0:
            return False, "每份热量必须是非负整数"
        if not gram_per_piece or not isinstance(gram_per_piece, int) or gram_per_piece <= 0:
            return False, "每份克重必须是正整数"

        # 2. 校验类别是否存在（双重校验，更稳妥）
        cate_exists, _ = FoodCateServices.get_food_cate_by_id(food_cate_id)
        if not cate_exists:
            return False, f"关联的食物类别ID {food_cate_id} 不存在，请先创建该类别"

        # 3. 调用 DAO 层新增
        try:
            new_food = FoodCalDAO.add_food_cal(food_cate_id, food_name, kcal_per_piece, gram_per_piece)
            return True, f"新增食物热量记录成功！ID：{new_food.id}，食物：{new_food.food_name}"
        except IntegrityError as e:
            return False, str(e).split("\n")[0]
        except ValueError as e:
            return False, str(e)
        except SQLAlchemyError as e:
            return False, f"新增失败：{str(e)}"
        except Exception as e:
            return False, f"系统异常：{str(e)}"

    @staticmethod
    def get_food_cal_by_id(food_id):
        """
        根据 ID 查询食物热量记录（含类别名称）
        :param food_id: 食物记录 ID
        :return: (bool, dict/str) - (成功标识, 数据字典/提示信息)
        """
        # 1. 参数校验
        if not food_id or not isinstance(food_id, int) or food_id <= 0:
            return False, "食物ID必须是正整数"

        # 2. 调用 DAO 层查询
        try:
            food_dict = FoodCalDAO.get_food_cal_by_id(food_id)
            if food_dict:
                return True, food_dict
            else:
                return False, f"未查询到 ID 为 {food_id} 的食物热量记录"
        except SQLAlchemyError as e:
            return False, f"查询失败：{str(e)}"
        except Exception as e:
            return False, f"系统异常：{str(e)}"

    @staticmethod
    def get_food_cal_by_name(food_name):
        """
        根据名称查询食物热量记录（精确匹配，含类别名称）
        :param food_name: 食物名称
        :return: (bool, dict/str) - (成功标识, 数据字典/提示信息)
        """
        # 1. 参数校验
        if not food_name or food_name.strip() == "":
            return False, "查询名称不能为空"

        # 2. 调用 DAO 层查询
        try:
            food_dict = FoodCalDAO.get_food_cal_by_name(food_name)
            if food_dict:
                return True, food_dict
            else:
                return False, f"未查询到名称为 {food_name} 的食物热量记录"
        except SQLAlchemyError as e:
            return False, f"查询失败：{str(e)}"
        except Exception as e:
            return False, f"系统异常：{str(e)}"

    @staticmethod
    def get_all_food_cals():
        """
        查询所有食物热量记录（含类别名称）
        :return: (bool, list/str) - (成功标识, 数据列表/提示信息)
        """
        try:
            food_list = FoodCalDAO.get_all_food_cals()
            return True, food_list
        except SQLAlchemyError as e:
            return False, f"查询所有食物热量记录失败：{str(e)}"
        except Exception as e:
            return False, f"系统异常：{str(e)}"

    @staticmethod
    def get_food_cals_by_cate_id(food_cate_id):
        """
        根据食物类别ID，查询该类别下的所有食物记录（含类别名称）
        :param food_cate_id: 食物类别ID
        :return: (bool, list/str) - (成功标识, 数据列表/提示信息)
        """
        # 1. 参数校验
        if not food_cate_id or not isinstance(food_cate_id, int) or food_cate_id <= 0:
            return False, "食物类别ID必须是正整数"

        # 2. 调用 DAO 层查询
        try:
            food_list = FoodCalDAO.get_food_cals_by_cate_id(food_cate_id)
            if food_list:
                return True, food_list
            else:
                return True, f"类别ID {food_cate_id} 下无关联的食物记录"
        except SQLAlchemyError as e:
            return False, f"查询失败：{str(e)}"
        except Exception as e:
            return False, f"系统异常：{str(e)}"

    @staticmethod
    def update_food_cal(food_id, **kwargs):
        """
        根据 ID 更新食物热量记录（支持部分字段更新）
        :param food_id: 食物记录 ID
        :param kwargs: 要更新的字段（可选：food_cate_id、food_name、kcal_per_piece、gram_per_piece）
        :return: (bool, str) - (成功标识, 提示信息)
        """
        # 1. 基础参数校验
        if not food_id or not isinstance(food_id, int) or food_id <= 0:
            return False, "食物ID必须是正整数"
        if not kwargs:
            return False, "请传入要更新的字段"

        # 2. 校验更新字段的合法性
        update_msg = []
        if "food_cate_id" in kwargs:
            new_cate_id = kwargs["food_cate_id"]
            if not isinstance(new_cate_id, int) or new_cate_id <= 0:
                return False, "更新失败：食物类别ID必须是正整数"
            # 校验新类别是否存在
            cate_exists, _ = FoodCateServices.get_food_cate_by_id(new_cate_id)
            if not cate_exists:
                return False, f"更新失败：关联的食物类别ID {new_cate_id} 不存在"
            update_msg.append(f"类别ID：{new_cate_id}")

        if "food_name" in kwargs:
            new_name = kwargs["food_name"].strip()
            if not new_name:
                return False, "更新失败：食物名称不能为空"
            update_msg.append(f"名称：{new_name}")

        if "kcal_per_piece" in kwargs:
            new_kcal = kwargs["kcal_per_piece"]
            if not isinstance(new_kcal, int) or new_kcal < 0:
                return False, "更新失败：每份热量必须是非负整数"
            update_msg.append(f"每份热量：{new_kcal}kcal")

        if "gram_per_piece" in kwargs:
            new_gram = kwargs["gram_per_piece"]
            if not isinstance(new_gram, int) or new_gram <= 0:
                return False, "更新失败：每份克重必须是正整数"
            update_msg.append(f"每份克重：{new_gram}g")

        # 3. 调用 DAO 层更新
        try:
            updated_food = FoodCalDAO.update_food_cal(food_id, **kwargs)
            if updated_food:
                return True, f"更新成功！ID：{food_id}，更新内容：{', '.join(update_msg)}"
            else:
                return False, f"更新失败：未查询到 ID 为 {food_id} 的食物热量记录"
        except IntegrityError as e:
            return False, str(e).split("\n")[0]
        except ValueError as e:
            return False, str(e)
        except SQLAlchemyError as e:
            return False, f"更新失败：{str(e)}"
        except Exception as e:
            return False, f"系统异常：{str(e)}"

    @staticmethod
    def delete_food_cal(food_id):
        """
        根据 ID 删除食物热量记录
        :param food_id: 食物记录 ID
        :return: (bool, str) - (成功标识, 提示信息)
        """
        # 1. 参数校验
        if not food_id or not isinstance(food_id, int) or food_id <= 0:
            return False, "食物ID必须是正整数"

        # 2. 调用 DAO 层删除
        try:
            success = FoodCalDAO.delete_food_cal(food_id)
            if success:
                return True, f"删除成功：ID {food_id} 的食物热量记录已删除"
            else:
                return False, f"删除失败：未查询到 ID 为 {food_id} 的食物热量记录"
        except SQLAlchemyError as e:
            return False, f"删除失败：{str(e)}"
        except Exception as e:
            return False, f"系统异常：{str(e)}"

    @staticmethod
    def search_food_cals_by_keyword(keyword):
        """
        按关键词模糊查询食物记录（匹配食物名称，含类别名称）
        :param keyword: 搜索关键词
        :return: (bool, list/str) - (成功标识, 数据列表/提示信息)
        """
        # 1. 参数校验
        if not keyword or keyword.strip() == "":
            return False, "搜索关键词不能为空"

        # 2. 调用 DAO 层查询
        try:
            food_list = FoodCalDAO.search_food_cals_by_keyword(keyword)
            if food_list:
                return True, food_list
            else:
                return True, f"未查询到包含关键词「{keyword}」的食物记录"
        except SQLAlchemyError as e:
            return False, f"搜索失败：{str(e)}"
        except Exception as e:
            return False, f"系统异常：{str(e)}"